﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IESN.Communication;
using System.Threading;
using System.Windows.Forms;
using IESN.DM;
using Microsoft.VisualBasic.CompilerServices;
using IESN.Enum;
using IESN.Common;

namespace IESN.BusinessCore
{
    /// <summary>
    /// Worker由Controller来进行控制
    /// </summary>
    public  class Worker
    {
        #region 变量

        /// <summary>
        /// 是否使用西门子PLC
        /// </summary>
        private bool _isSimensPlc = false;

        private Controller _mController;

        /// <summary>
        /// PLC连接对象
        /// </summary>
        private IPLC _objcomm; 

        #endregion

        #region 初始化

        /// <summary>
        /// 构造函数
        /// </summary>
        public Worker()
        {
            InitPlcCommunication();
        }

        /// <summary>
        /// 初始化PLC通讯方式
        /// </summary>
        private void InitPlcCommunication()
        {
            if (AppConfiguration.CurrentCommType == Enums.EnumCommType.Comm)   //0xe8 即232
            {
                this._objcomm = new Comm(AppConfiguration.LinkAddr, AppConfiguration.PortNum, AppConfiguration.BaudRate, AppConfiguration.TimeOut);
            }
            else if (AppConfiguration.CurrentCommType == Enums.EnumCommType.SysmacAx)
            {
                this._objcomm = new SysmacAx(AppConfiguration.EtNodeAddr, AppConfiguration.EtUnitAddr);
            }
            else
            {
                this._isSimensPlc = true;
                this._objcomm = new SimenAPI(AppConfiguration.AdrTable, 1);
            }
        }

        #endregion
        
        public void Initialize(Controller Controller)
        {
            this._mController = Controller;
        }

        /// <summary>
        /// 启动
        /// </summary>
        /// <param name="state"></param>
        public void Start(object state)
        {
            short dmObjectCollectCount = 0;
            short num3 = 0;
            try
            {
                dmObjectCollectCount = this._mController.DmObjectCollectCount;
                Thread.Sleep(1500);

                while (true)
                {
                    if (!this._mController.IsRunning)
                    {
                        break;
                    }
                    if (!this._mController.PauseWorkerThread)
                    {
                        try
                        {
                            num3++;
                            if (num3 > Initialization.DMRunCycle)
                            {
                                num3 = 1;
                            }
                           
                            //循环每个DM对象
                            foreach(DmClass dmObject in GlobalCache.GetInstance.DmMapping.Values)
                            {
                                #region 循环内存对象集合
                                
                                if (!this._mController.IsRunning)
                                {
                                    break;
                                }

                                //为解决内存对象更新频率问题，通过 ObjRunIndex 和　DMRunCycle 来决定， 
                                if (dmObject.DmAddress > 0 && 
                                    (dmObject.ObjRunIndex == 0 || 
                                    (dmObject.ObjRunIndex > 0 &&
                                    ((short)(dmObject.ObjRunIndex % Initialization.DMRunCycle) == num3 || ((short)(dmObject.ObjRunIndex % Initialization.DMRunCycle) == 0))
                                    )))
                                {
                                   
                                    if (dmObject.DmStatus && dmObject.DmType == DmRWType.Read)
                                    {
                                        ReadDM(dmObject);
                                    }

                                    //内存对像状态为true，内存操作类型为写操作、设置位操作、重置位操作
                                    if (dmObject.DmStatus &&
                                        (dmObject.DmType == DmRWType.Write || dmObject.DmType == DmRWType.SetBit || dmObject.DmType == DmRWType.ResetBit))
                                    {
                                        //写DM操作
                                        WriteDM(dmObject);
                                    }
                                }
                                this.doevents();

                                #endregion
                            }
                            //this.doevents();
                        }
                        catch (Exception exception12)
                        {
                            ProjectData.SetProjectError(exception12);
                            Exception objException = exception12;
                            //app.LogError(objException);     todo
                            ProjectData.ClearProjectError();
                        }
                        //this.doevents();
                    }
                    //this.doevents();
                  
                }
                this._objcomm.CloseComm();
                this._objcomm = null;
                //this.doevents();
            }
            catch (Exception exception13)
            {
                ProjectData.SetProjectError(exception13);
                Exception exception7 = exception13;
                this._objcomm.CloseComm();
                this._objcomm = null;
                //this.doevents();
                //app.LogError(exception7);
                //this.doevents();
                ProjectData.ClearProjectError();
            }
            //this.doevents();
        }

        #region 读取DM

        /// <summary>
        /// 读取DM
        /// </summary>
        /// <param name="dmObject"></param>
        private void ReadDM(DmClass dmObject)
        {
            this._objcomm.Status_NRead = 0;  //LGH 通讯TODO
            if (dmObject.DbBlockAddr > 0)
            {
                this._objcomm.DBNo = dmObject.DbBlockAddr;
            }

            #region 如果是Simens的Plc

            if (this._isSimensPlc)
            {
                //dmObject中写死了用"W"类型
                if (string.Compare(dmObject.DataType, "M", false) == 0)
                {
                    this._objcomm.NReadWord((short)dmObject.DmAddress, dmObject.DmCount, ref dmObject.dmContentByteArry); //该方法没有实现
                    //this.doevents();
                    //this.doevents();
                }
                else
                {
                    dmObject.DmContent = this._objcomm.NReadWord((short)dmObject.DmAddress, dmObject.DmCount, dmObject.DataType);
                    //this.doevents();
                    //this.doevents();
                }
            }

            #endregion

            else//其他PLC
            {
                //天车或Pcode,会一直读到完成
                if (dmObject.DmObjectId == Initialization.intXP_Display || dmObject.DmObjectId == Initialization.intPcodeArea)
                {
                    do
                    {
                        //this.doevents();
                        //this.doevents();
                        dmObject.DmContent = this._objcomm.NReadWord((short)dmObject.DmAddress, dmObject.DmCount);
                        
                    }
                    while (!(this._objcomm.Status_NRead == 1 && dmObject.DmContent.Length == (dmObject.DmCount * 4))); //读取的内容长度和dmCount*4相同,按字读取
                }
                else
                {
                    //this.doevents();
                    //this.doevents();
                    dmObject.DmContent = this._objcomm.NReadWord((short)dmObject.DmAddress, dmObject.DmCount);  //LGH 通讯TODO
                   
                }
                //this.doevents();
            }

            //如何读状态为1
            if (this._objcomm.Status_NRead == 1)   //LGH  TODO
            //if(1==1)  
            {
                //设置PLC在线标志
                this._mController.IsOnLine = true;

                //如何是条件对像，同时条件对像处理方法存在，则触发委托事件进行解析数据内存
                if (dmObject.IsCondiObject && dmObject.DmObjectCondiProcessMethod != null)
                {
                    try
                    {
                        //dmObject.DmObjectCondiProcessMethod(dmObject);
                        dmObject.DmObjectCondiProcessMethod.BeginInvoke(dmObject, null, null); //触发委托事件进行解析数据内存
                    }
                    catch (Exception exception1)
                    {
                        ProjectData.SetProjectError(exception1);
                        Exception exception = exception1;
                        ProjectData.ClearProjectError();
                    }
                }

                //如何DM运行的事件处理线程状态为真
                if (dmObject.DmRunEventProcessThreadStatus)
                {
                    if (dmObject.DmNodeType == DmNodeType.Child) //子节点 dmstatus设置false 
                    {
                        dmObject.DmStatus = false;
                    }
                    dmObject.DmRunEventProcessThreadStatus = false;

                    //内存对象事件处理方法存在，同时，内存数据长度大小，与指定内存大小的倍数相同，（乘4的意思是，DmCount指的是一个字，一个字转成字符是4个字符）
                    //触发委托事件进行解析数据内存
                    if (dmObject.DmObjectEventProcessMethod != null && dmObject.DmContent.Length == (dmObject.DmCount * 4))
                    {
                        try
                        {
                            //dmObject.DmObjectEventProcessMethod(dmObject);
                            dmObject.DmObjectEventProcessMethod.BeginInvoke(dmObject, null, null); //触发委托事件进行解析数据内存
                        }
                        catch (Exception exception8)
                        {
                            ProjectData.SetProjectError(exception8);
                            Exception exception2 = exception8;
                            ProjectData.ClearProjectError();
                        }
                    }
                }

                if (dmObject.DmNodeType == DmNodeType.Child) //子节点 dmstatus设置false 
                {
                    dmObject.DmStatus = false;
                }

              
                //让用到数据的窗口，各自读内存，并解析数据
                this._mController.ReadDM(dmObject);
                //this.doevents();

                //休息10毫秒
                Thread.Sleep(10);
                //this.doevents();
            }
            else
            {
                //PLC掉线
                this._mController.IsOnLine = false;
            }
        }

        #endregion

        #region 写DM

        /// <summary>
        /// 写DM
        /// </summary>
        /// <param name="dmObject"></param>
        private void WriteDM(DmClass dmObject)
        {
            if (dmObject.DmNodeType == DmNodeType.Child &&
                (dmObject.DmObjectEventProcessMethod != null && dmObject.DmRunEventProcessThreadStatus))
            {
                dmObject.DmRunEventProcessThreadStatus = false;
                try
                {
                    dmObject.DmObjectEventProcessMethod(dmObject);
                }
                catch (Exception exception9)
                {
                    ProjectData.SetProjectError(exception9);
                    Exception exception3 = exception9;
                    ProjectData.ClearProjectError();
                }
            }

            Application.DoEvents();
            dmObject.DmStatus = false;
            this._objcomm.Status_NWrite = 0;
            this._objcomm.Status_NSetbit = 0;
            this._objcomm.Status_NResetbit = 0;

            //写操作
            if (dmObject.DmType == DmRWType.Write)
            {
                if (dmObject.W_ElemCountS > 0 && dmObject.W_Elem_Used)
                {
                    short num9 = (short)(dmObject.W_ElemCountS - 1);
                    for (short index = 0; index <= num9; index++)
                    {
                        if (dmObject.W_elem_status[index])
                        {
                            dmObject.W_elem_status[index] = false;
                            if (dmObject.DbBlockAddr > 0)
                            {
                                this._objcomm.DBNo = dmObject.DbBlockAddr;
                            }
                            if (this._isSimensPlc)
                            {
                                this._objcomm.NWriteWord((short)(dmObject.DmAddress + (dmObject.W_elem_offset[index] * 2)), 0, dmObject.W_elem_Content[index], dmObject.DataType);
                                //this.doevents();
                                //this.doevents();
                                //this.doevents();
                            }
                            else
                            {
                                this._objcomm.NWriteWord((short)(dmObject.DmAddress + dmObject.W_elem_offset[index]), 0, dmObject.W_elem_Content[index]);
                                //this.doevents();
                                //this.doevents();
                                //this.doevents();
                            }
                        }
                    }
                }
                else
                {
                    if (dmObject.DbBlockAddr > 0)
                    {
                        this._objcomm.DBNo = dmObject.DbBlockAddr;
                    }
                    if (this._isSimensPlc)
                    {
                        if (string.Compare(dmObject.DataType, "M", false) == 0)
                        {
                            this._objcomm.NWriteWord((short)dmObject.DmAddress, 0, dmObject.dmContentByteArry);
                            //this.doevents();
                            //this.doevents();
                        }
                        else
                        {
                            this._objcomm.NWriteWord((short)dmObject.DmAddress, 0, dmObject.DmContent, dmObject.DataType);
                            //this.doevents();
                            //this.doevents();
                        }
                    }
                    else
                    {
                        this._objcomm.NWriteWord((short)dmObject.DmAddress, 0, dmObject.DmContent);
                        //this.doevents();
                        //this.doevents();
                    }
                }
                if (dmObject.IsDisplayed)
                {
                    this._mController.ReadDM(dmObject);
                    //this.doevents();
                    Thread.Sleep(10);
                    //this.doevents();
                }
            }

            //按位重置操作
            if (dmObject.DmType == DmRWType.ResetBit)
            {
                if (dmObject.W_ElemCountS > 0 && dmObject.W_Elem_Used)
                {
                    short num8 = (short)(dmObject.W_ElemCountS - 1);
                    for (short num5 = 0; num5 <= num8; num5++)
                    {
                        if (dmObject.W_elem_status[num5])
                        {
                            dmObject.W_elem_status[num5] = false;
                            if (dmObject.DbBlockAddr > 0)
                            {
                                this._objcomm.DBNo = dmObject.DbBlockAddr;
                            }
                            this._objcomm.NResetBit((short)dmObject.DmAddress, Convert.ToInt16(dmObject.W_elem_Content[num5]));
                            //this.doevents();
                        }
                    }
                }
                else
                {
                    if (dmObject.DbBlockAddr > 0)
                    {
                        this._objcomm.DBNo = dmObject.DbBlockAddr;
                    }
                    this._objcomm.NResetBit((short)dmObject.DmAddress, Convert.ToInt16(dmObject.DmContent));
                    //this.doevents();
                }
            }

            //按位写操作
            if (dmObject.DmType == DmRWType.SetBit)
            {
                if (dmObject.W_ElemCountS > 0 && dmObject.W_Elem_Used)
                {
                    //short num6 = 0;
                    short num7 = (short)(dmObject.W_ElemCountS - 1);
                    for (short num6 = 0; num6 <= num7; num6++)
                    {
                        if (dmObject.W_elem_status[num6])
                        {
                            dmObject.W_elem_status[num6] = false;
                            if (dmObject.DbBlockAddr > 0)
                            {
                                this._objcomm.DBNo = dmObject.DbBlockAddr;
                            }
                            this._objcomm.NSetBit((short)dmObject.DmAddress, Convert.ToInt16(dmObject.W_elem_Content[num6]));
                            //this.doevents();
                        }
                    }
                }
                else
                {
                    if (dmObject.DbBlockAddr > 0)
                    {
                        this._objcomm.DBNo = dmObject.DbBlockAddr;
                    }
                    this._objcomm.NSetBit((short)dmObject.DmAddress, Convert.ToInt16(dmObject.DmContent));
                    //this.doevents();
                }
            }

            ///////////////////////////
            if ((((this._objcomm.Status_NWrite == 1) | (this._objcomm.Status_NResetbit == 1)) | (this._objcomm.Status_NSetbit == 1)) && (dmObject.DmNodeType == DmNodeType.Parent))
            {
                ///////////
                if (dmObject.IsCondiObject && (dmObject.DmObjectCondiProcessMethod != null))
                {
                    try
                    {
                        dmObject.DmObjectCondiProcessMethod(dmObject);
                    }
                    catch (Exception exception10)
                    {
                        ProjectData.SetProjectError(exception10);
                        Exception exception4 = exception10;
                        ProjectData.ClearProjectError();
                    }
                }
                //////////
                if ((dmObject.DmObjectEventProcessMethod != null) & dmObject.DmRunEventProcessThreadStatus)
                {
                    dmObject.DmRunEventProcessThreadStatus = false;
                    try
                    {
                        dmObject.DmObjectEventProcessMethod(dmObject);
                    }
                    catch (Exception exception11)
                    {
                        ProjectData.SetProjectError(exception11);
                        Exception exception5 = exception11;
                        ProjectData.ClearProjectError();
                    }
                }
            }

        }

        #endregion
        
        private void doevents()
        {
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
            Application.DoEvents();
        }

    }
}